home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-04-16 | 10.3 KB | 445 lines | [TEXT/CWIE] |
- Unit Binhex;
- {$NR+}
-
- Interface
-
- Uses
- Toolbox, DropBinUtils, BinProgress;
-
- Const
- BinHexOpen = 5807;
- BufferSize = 4096;
- MemErr = 6417;
- BinHexRead = 5811;
- BinHexTable = '!"#$%&''()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr';
- BinHexHeader = '(This file must be converted with BinHex 4.0)';
-
- Var
- DontTranslate: Boolean; { don't use translation tables }
- CommandPeriod: Boolean; { has cmd-. been pressed lately? }
- State86: SignedByte;
- SavedBits: SignedByte;
- LineLength: SignedByte;
-
- Function BinHexFile(vRef: integer; dirId: longint; name: str255): integer;
-
- Implementation
-
- {************************************************************************
- * EncodeDataChar - encode an 8-bit data char into a six-bit buffer
- * returns the number of valid encoded characters generated
- ************************************************************************}
- Function EncodeDataChar(c: SignedByte; toSpot: Ptr): integer;
-
- Var
- spotWas: Ptr;
-
- Procedure Addnewline;
-
- begin
- linelength := 0;
- toSpot^ := kReturnKey;
- OffsetPtr(toSpot,1);
- end;
-
- Var
- i: integer;
-
- begin
- spotWas := toSpot;
- case State86 of
- 0: begin
- i := BAnd(BSR(c,2),$3F);
- toSpot^ := SignedByte(BinHexTable[i+1]);
- OffsetPtr(toSpot, 1);
- SavedBits := BSL(BAnd(c,$03),4);
- inc(lineLength);
- if lineLength = 64 then
- Addnewline;
- end;
- 1: begin
- i := BOr(SavedBits,BAnd(BSR(c,4),$0F));
- toSpot^ := SignedByte(BinHexTable[i+1]);
- OffsetPtr(toSpot, 1);
- SavedBits := BSL(BAnd(c,$0f),2);
- inc(lineLength);
- if lineLength = 64 then
- Addnewline;
- end;
- 2: begin
- i := BOr(SavedBits,BAnd(BSR(c,6),$03));
- toSpot^ := SignedByte(BinHexTable[i+1]);
- OffsetPtr(toSpot, 1);
- inc(lineLength);
- if lineLength = 64 then
- Addnewline;
- i := BAnd(c,$3f);
- toSpot^ := SignedByte(BinHexTable[i+1]);
- OffsetPtr(toSpot, 1);
- inc(lineLength);
- if lineLength = 64 then
- Addnewline;
- State86 := -1;
- end;
- end; { of CASE }
- inc(State86);
- EncodeDataChar := ORD4(toSpot) - ORD4(spotWas);
- end;
-
- Procedure CalcCRC(c: unsignedWord);
-
- Const
- ByteMask = $0FF;
- WordMask = $0FFFF;
- WordBit = $10000;
- CrcConstant = $01021;
-
- Var
- i: integer;
-
- begin
- c := BAnd(c, ByteMask);
- for i := 1 to 8 do
- begin
- c := BSL(c,1);
- mainCRC := BSL(mainCRC,1);
- if BAnd(mainCRC,WordBit) <> 0 then
- mainCRC := BXOr(BAnd(mainCRC,WordMask), CrcConstant);
- mainCRC := BXOr(mainCRC,BSR(c,8));
- c := BAnd(c, ByteMask);
- end;
- end;
-
- Procedure Code(dc: SignedByte; var codedSpot: integer; codedBuffer: Ptr);
-
- Procedure LCode(dc: SignedByte);
-
- begin
- codedSpot := codedSpot +
- EncodeDataChar(dc,Ptr(ORD4(codedBuffer) + codedSpot));
- end;
-
- begin
- LCode(dc);
- if dc = -112 then
- LCode(0);
- CalcCRC(dc);
- end;
-
- Procedure CodeShort(ds: integer; var codedSpot: integer; codedBuffer: Ptr);
-
- Var
- cp: Ptr;
-
- begin
- cp := @ds;
- Code(cp^, codedSpot, codedBuffer);
- Code(AddPtrLong(cp,1)^, codedSpot, codedBuffer);
- end;
-
- Procedure CodeShortInt(ds: integer; var codedSpot: integer; codedBuffer: Ptr);
-
- Var
- cp: Ptr;
-
- begin
- cp := @ds;
- Code(AddPtrLong(cp,1)^, codedSpot, codedBuffer);
- Code(cp^, codedSpot, codedBuffer);
- end;
-
- Procedure CodeLong(dl: longint; var codedSpot: integer; codedBuffer: Ptr);
-
- Var
- copy: longint;
- cp: Ptr;
-
- begin
- copy := dl;
- cp := @dl;
- Code(cp^, codedSpot, codedBuffer);
- Code(AddPtrLong(cp,1)^, codedSpot, codedBuffer);
- Code(AddPtrLong(cp,2)^, codedSpot, codedBuffer);
- Code(AddPtrLong(cp,3)^, codedSpot, codedBuffer);
- end;
-
- Function WriteBuffer(buffptr: univ Ptr; buffsize: longint): integer;
-
- begin
- WriteBuffer := FSWrite(gRefNum, buffsize, buffptr);
- end;
-
- Procedure WriteZero(pointer: Ptr; size: longint);
-
- begin
- while size > 0 do
- begin
- pointer^ := 0;
- OffsetPtr(pointer,1);
- dec(size);
- end;
- end;
-
- Function DeleteFile(name: str255; vRefN: integer; dirId: longint): integer;
-
- Var
- pb: HParamBlockRec;
-
- begin
- if FSClose(gRefNum) = 0 then;
- pb.ioNamePtr := @name;
- pb.ioVRefNum := vRefN;
- pb.ioMisc := nil;
- HFileParamPtr(@pb)^.ioDirID := dirID;
- DeleteFile := PBHDeleteSync(@pb);
- end;
-
- Function FSHOpen(name: str255; vRefN: integer; dirId: longint;
- var refN: integer; perm: integer): integer;
-
- Var
- pb: HParamBlockRec{HIOParam};
- err: integer;
-
- begin
- pb.ioNamePtr := @name;
- pb.ioVRefNum := vRefN;
- pb.ioPermssn := perm;
- pb.ioMisc := nil;
- HFileParamPtr(@pb)^.ioDirID := dirID;
- err := PBHOpenSync(@pb);
- if err = noErr then
- refN := pb.ioRefNum;
- FSHOpen := err;
- end;
-
- Function RFHOpen(name: Str255; vRefN: integer; dirId: longint;
- var refN: integer; perm: integer): integer;
-
- Var
- pb: HParamBlockRec;
- err: integer;
-
- begin
- pb.ioCompletion := nil;
- pb.ioNamePtr := @name;
- pb.ioVRefNum := vRefN;
- pb.ioVersNum := 0;
- pb.ioPermssn := perm;
- pb.ioMisc := nil;
- HFileParamPtr(@pb)^.ioDirID := dirID;
- err := PBHOpenRFSync(@pb);
- if err = noErr then
- refN := pb.ioRefNum;
- RFHOpen := err;
- end;
-
- Function HGetFileInfo(vRef: integer; dirId: longint; name: str255; var hfi: HFileParam): integer;
-
- Var
- oe: integer;
-
- begin
- WriteZero(@hfi,sizeof(hfi));
- hfi.ioNamePtr := @name;
- hfi.ioVRefNum := vRef;
- hfi.ioDirID := dirID;
- oe := PBHGetFInfoSync(@hfi);
- HGetFileInfo := oe;
- end;
-
- Function AddCRC(var idx: integer; codedBuffer: Ptr): OSErr;
-
- Var
- tempCrc: integer;
-
- begin
- CalcCRC(0);
- CalcCRC(0);
- tempCrc := BAnd(mainCRC, $FFFF);
- CodeShort(tempCrc, idx, codedBuffer);
- mainCRC := 0;
- AddCRC := WriteBuffer(codedBuffer, idx);
- end;
-
- {************************************************************************
- * BinHexFork - send one fork of a file as BinHex data
- ************************************************************************}
- Function BinHexFork(refN: integer; dataBuffer: Ptr; dataSize: integer;
- codedBuffer: Ptr; name: Str255): integer;
-
- Var
- dataEnd: longint;
- bindex: integer;
- err: OSErr;
- spot: Ptr;
- errWas: OSErr;
-
- begin
- bindex := 0;
- repeat
- dataEnd := dataSize;
- err := FSRead(refN, dataEnd, dataBuffer);
- if (err = noErr) or (err = eofErr) then
- begin
- errWas := err;
- spot := dataBuffer;
- while ORD4(spot) < ORD4(dataBuffer) + dataEnd do
- begin
- Code(spot^, bindex, codedBuffer);
- OffsetPtr(spot, 1);
- end;
- err := WriteBuffer(codedBuffer, bindex);
- bindex := 0;
- if err = noErr then
- err := errWas;
- if UpdateProgress(dataEnd) <> 0 then
- begin
- DisplayMsg('Binhex operation cancelled on file "'+gFilename+'".');
- BinHexFork := -1;
- exit(BinHexFork);
- end;
- end;
- if (err <> noErr) and (err <> eofErr) and (not CommandPeriod) then
- AlertUser(name,err);
- until err <> noErr;
- if err = eofErr then
- err := addCRC(bindex, codedBuffer);
- if err = eofErr then
- BinHexFork := noErr
- else
- BinHexFork := err;
- end; { of BinHexFork }
-
- {************************************************************************
- * BinHexFile - convert a file to BinHex data
- ************************************************************************}
- Function BinHexFile(vRef: integer; dirId: longint; name: str255): integer;
-
- Var
- refN: integer;
- dataBuffer: Ptr;
- codedBuffer: Ptr;
- dataSize,
- codedSize: longint;
- i,codedSpot: integer;
- err: OSErr;
- hfp: HFileParam;
- scratch: Str255;
-
- Procedure ExitBinHex(e: integer);
-
- begin
- if refN <> 0 then
- if FSClose(refN) = 0 then;
- if dataBuffer <> NIL then
- DisposePtr(Ptr(dataBuffer));
- if codedBuffer <> NIL then
- DisposePtr(Ptr(codedBuffer));
- gProcessing := false;
- InvalRect(dbWindow^.portRect);
- DontTranslate := False;
- if e <> noErr then
- begin
- e := DeleteFile(gOutputName, vRef, dirId);
- if e <> noErr then
- AlertUser('Error deleting file ' + gOutputName, e);
- EndProgress;
- ResetWindow(dbWindow);
- end
- else
- EndProgress;
- BinHexFile := e;
- exit(BinHexFile);
- end; { of ExitBinHex }
-
- Procedure FailError(msg: str255; e: integer);
-
- begin
- AlertUser(msg, e);
- ExitBinHex(e);
- end; { of FailError }
-
- begin
- if gState then
- begin
- SetupProgress;
- gState := false;
- end;
- gProcessing := true;
- gFilename := name;
- refN := 0;
- dataBuffer := NIL;
- codedBuffer := NIL;
- err := HGetFileInfo(vRef,dirId,name,hfp);
- if err <> noErr then
- FailError('Error reading file header for ' + name, err); { file error }
- { allocate the buffers }
- codedSize := 4096;
- dataSize := codedSize div 3;
- dataBuffer := NewPtrClear(datasize);
- codedBuffer := NewPtrClear(codedsize);
- if (dataBuffer = NIL) or (codedBuffer = NIL) then
- FailError('Not enough memory', -108); { Memory error }
- StartProgress(hfp.ioFlLgLen+hfp.ioFlRLgLen);
- { set the header }
- scratch := chr(13) + BinHexHeader + chr(13) + chr(13) + ':';
- err := WriteBuffer(@scratch[1], integer(scratch[0]));
- if err <> noErr then
- FailError('Error writing header', err); { Header error }
- { set the file information }
- DontTranslate := True;
- LineLength := 1;
- State86 := 0;
- mainCRC := 0;
- codedSpot := 0;
- for i := 0 to length(name) do
- Code(byte(name[i]), codedSpot, codedBuffer);
- Code(0, codedSpot, codedBuffer);
- CodeLong(longint(hfp.ioFlFndrInfo.fdType), codedSpot, codedBuffer);
- CodeLong(longint(hfp.ioFlFndrInfo.fdCreator), codedSpot, codedBuffer);
- CodeShort(integer(hfp.ioFlFndrInfo.fdFlags), codedSpot, codedBuffer);
- CodeLong(longint(hfp.ioFlLgLen), codedSpot, codedBuffer);
- CodeLong(longint(hfp.ioFlRLgLen), codedSpot, codedBuffer);
- err := addCRC(codedSpot, codedBuffer);
- if err <> noErr then
- FailError('Error calculating CRC for header', err);
- { data fork }
- codedSpot := 0;
- if vRef = 0 then
- FailError('Invalid value for volume reference',-1);
- err := FSHOpen(name,vRef,dirId,refN,fsRdPerm);
- if err <> noErr then
- FailError('Error opening data fork', err);
- err := BinHexFork(refN, dataBuffer, dataSize, codedBuffer, name);
- if err = -1 then
- ExitBinHex(err)
- else if err <> noErr then
- FailError('Error encoding data fork',err);
- { resource fork }
- codedSpot := 0;
- if refN <> 0 then
- FSClose(refN);
- refN := 0;
- err := RFHOpen(name,vRef,dirId,refN,fsRdPerm);
- if err <> noErr then
- FailError('Error opening resource fork', err);
- err := BinHexFork(refN, dataBuffer, dataSize, codedBuffer, name);
- if err = -1 then
- ExitBinHex(err)
- else if err <> noErr then
- FailError('Error encoding resource fork', err);
- { leftovers }
- if State86 <> 0 then
- Code(0, codedSpot, codedBuffer);
- PtrUpdate(codedBuffer,codedSpot,':');
- inc(codedSpot);
- PtrUpdate(codedBuffer,codedSpot,chr(13));
- inc(codedSpot);
- err := WriteBuffer(codedBuffer,codedSpot);
- if err <> noErr then
- FailError('Error completing binhex encoding', err);
- ExitBinHex(noErr);
- end;
-
- End.